/*
 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef OHOS_SHARING_RTMP_COMMON_H
#define OHOS_SHARING_RTMP_COMMON_H

#include <cstdint>
#include <cstdlib>
#include <memory>
#include "data_buffer.h"
#include "rtmp_amf.h"

namespace OHOS {
namespace Sharing {

#define FLV_CODEC_H264 7
#define FLV_CODEC_AAC  10

#define FLV_KEY_FRAME   1
#define FLV_INTER_FRAME 2

#define STREAM_CONTROL 0
#define STREAM_MEDIA   1

#define DEFAULT_CHUNK_LEN   128
#define HANDSHAKE_PLAINTEXT 0x03
#define RANDOM_LEN          (1536 - 8)

enum UserControlMessageEvents : uint8_t {
    CONTROL_STREAM_BEGIN = 0,
    CONTROL_STREAM_EOF = 1,
    CONTROL_STREAM_DRY = 2,
    CONTROL_SETBUFFER = 3,
    CONTROL_STREAM_ISRECORDED = 4,
    CONTROL_PING_REQUEST = 6,
    CONTROL_PING_RESPONSE = 7,
};

enum class RTMPMessageType : uint8_t {
    SET_CHUNK_SIZE = 1, ///< chunk size change
    ABORT_MESSAGE,
    ACKNOWLEDGEMENT = 3, ///< number of bytes read
    USER_CONTROL,        ///< user control
    WINDOW_ACK_SIZE,     ///< window acknowledgement size
    SET_PEER_BW,         ///< peer bandwidth
    AUDIO = 8,           ///< audio packet
    VIDEO = 9,           ///< video packet
    DATA3 = 15,          ///< Data Message (18, 15) AMF3
    OBJECT3 = 16,        ///< Shared Object Message (19, 16) AMF3
    CMD3 = 17,           ///< Command Message AMF3
    DATA = 18,           ///< Data Message (18, 15) AMF0
    OBJECT = 19,         ///< Shared Object Message (19, 16) AMF0
    CMD = 20,            ///< Command Message AMF0
    AGGRAGATE = 22,      ///< Aggregate Message (22)
};

#define CHUNK_NETWORK               2
#define CHUNK_SYSTEM                3
#define CHUNK_CLIENT_REQUEST_BEFORE 3
#define CHUNK_CLIENT_REQUEST_AFTER  4
#define CHUNK_AUDIO                 6
#define CHUNK_VIDEO                 7

struct RtmpHeader {
    uint8_t chunkId : 6;
    uint8_t fmt : 2;

    uint8_t timestamp[3];
    uint8_t messageLength[3];
    uint8_t typeId;
    // little-endian
    uint8_t streamId[4];
} __attribute__((packed));

struct RtmpHandshake {
    explicit RtmpHandshake(uint32_t time, uint8_t *random = nullptr);

    void RandomGenerate(char *bytes, int size);

    uint8_t timestamp[4];
    uint8_t zero[4] = {0};
    uint8_t random[RANDOM_LEN];
} __attribute__((packed));

class RtmpPacket : public DataBuffer {
public:
    friend class RtmpProtocol;
    using Ptr = std::shared_ptr<RtmpPacket>;

    static Ptr Create();
    void Clear() override;

    bool IsCfgFrame() const;
    bool IsVideoKeyFrame() const;

    int GetMediaType() const;
    int GetAudioChannel() const;
    int GetAudioSampleBit() const;
    int GetAudioSampleRate() const;

private:
    RtmpPacket()
    {
        Clear();
    }

    RtmpPacket &operator=(const RtmpPacket &that);

public:
    bool isAbsStamp;
    uint32_t tsField;
    uint32_t chunkId;
    uint32_t streamId;
    uint32_t timestamp;

    size_t bodySize;

    RTMPMessageType typeId;

} __attribute__((packed));
} // namespace Sharing
} // namespace OHOS
#endif // OHOS_SHARING_RTMP_COMMON_H
